/**

 @Name：layuiAdmin 视图模块
 @Author：贤心
 @Site：http://www.layui.com/admin/
 @License：LPPL

 */

layui.define(['laytpl', 'layer'], function(exports){
    var $ = layui.jquery
        ,laytpl = layui.laytpl
        ,layer = layui.layer
        ,setter = layui.setter
        ,device = layui.device()
        ,hint = layui.hint()

        //对外接口
        ,view = function(id){
            return new Class(id);
        }

        ,SHOW = 'layui-show', LAY_BODY = 'LAY_app_body'

        //构造器
        ,Class = function(id){
            this.id = id;
            this.container = $('#'+(id || LAY_BODY));
        };

    //加载中
    view.loading = function(elem){
        elem.append(
            this.elemLoad = $('<i class="layui-anim layui-anim-rotate layui-anim-loop layui-icon layui-icon-loading layadmin-loading"></i>')
        );
    };

    //移除加载
    view.removeLoad = function(){
        this.elemLoad && this.elemLoad.remove();
    };

    //清除 token，并跳转到登入页
    view.exit = function(){
        //清空本地记录的 token
        layui.data(setter.tableName, {
            key: setter.request.tokenName
            ,remove: true
        });

        //跳转到登入页
        location.hash = "/login";
    };

    //Ajax请求
    view.req = function(options){
        var that = this
            ,success = options.success
            ,error = options.error
            ,request = setter.request
            ,response = setter.response
            ,debug = function(){
            return setter.debug
                ? '<br><cite>URL：</cite>' + options.url
                : '';
        };

        options.data = options.data || {};
        options.headers = options.headers || {};

        if(request.tokenName){
            var sendData = typeof options.data === 'string'
                ? JSON.parse(options.data)
                : options.data;

            //自动给参数传入默认 token
            options.data[request.tokenName] = request.tokenName in sendData
                ?  options.data[request.tokenName]
                : (layui.data(setter.tableName)[request.tokenName] || '');

            //自动给 Request Headers 传入 token
            options.headers[request.tokenName] = request.tokenName in options.headers
                ?  options.headers[request.tokenName]
                : (layui.data(setter.tableName)[request.tokenName] || '');
        }

        delete options.success;
        delete options.error;

        return $.ajax($.extend({
            type: 'get'
            ,dataType: 'json'
            ,success: function(res){
                var statusCode = response.statusCode;

                //只有 response 的 code 一切正常才执行 done
                if(res[response.statusName] == statusCode.ok) {
                    typeof options.done === 'function' && options.done(res);
                }

                //登录状态失效，清除本地 access_token，并强制跳转到登入页
                else if(res[response.statusName] == statusCode.logout){
                    view.exit();
                }

                //其它异常
                else {
                    var error = [
                        '<cite>Error：</cite> ' + (res[response.msgName] || '返回状态码异常')
                        ,debug()
                    ].join('');
                    view.error(error);
                }

                //只要 http 状态码正常，无论 response 的 code 是否正常都执行 success
                typeof success === 'function' && success(res);
            }
            ,error: function(e, code){
                var error = [
                    '请求异常，请重试<br><cite>错误信息：</cite>'+ code
                    ,debug()
                ].join('');
                view.error(error);

                typeof error === 'function' && error(res);
            }
        }, options));
    };

    //弹窗
    view.popup = function(options){
        var success = options.success
            ,skin = options.skin;

        delete options.success;
        delete options.skin;

        return layer.open($.extend({
            type: 1
            ,title: '提示'
            ,content: ''
            ,id: 'LAY-system-view-popup'
            ,skin: 'layui-layer-admin' + (skin ? ' ' + skin : '')
            ,shadeClose: true
            ,closeBtn: false
            ,success: function(layero, index){
                var elemClose = $('<i class="layui-icon" close>&#x1006;</i>');
                layero.append(elemClose);
                elemClose.on('click', function(){
                    layer.close(index);
                });
                typeof success === 'function' && success.apply(this, arguments);
            }
        }, options))
    };

    //异常提示
    view.error = function(content, options){
        return view.popup($.extend({
            content: content
            ,maxWidth: 300
            //,shade: 0.01
            ,offset: 't'
            ,anim: 6
            ,id: 'LAY_adminError'
        }, options))
    };


    //请求模板文件渲染
    Class.prototype.render = function(views, params){
        var that = this, router = layui.router();
        views = setter.views + views + setter.engine;

        $('#'+ LAY_BODY).children('.layadmin-loading').remove();
        view.loading(that.container); //loading

        //请求模板
        $.ajax({
            url: views
            ,type: 'get'
            ,dataType: 'html'
            ,data: {
                v: layui.cache.version
            }
            ,success: function(html){
                html = '<div>' + html + '</div>';

                var elemTitle = $(html).find('title')
                    ,title = elemTitle.text() || (html.match(/\<title\>([\s\S]*)\<\/title>/)||[])[1];

                var res = {
                    title: title
                    ,body: html
                };

                elemTitle.remove();
                that.params = params || {}; //获取参数

                if(that.then){
                    that.then(res);
                    delete that.then;
                }

                that.parse(html);
                view.removeLoad();

                if(that.done){
                    that.done(res);
                    delete that.done;
                }

            }
            ,error: function(e){
                view.removeLoad();
                var status = e.status;
                switch (status) {
                    case 1001:
                        top.layer.alert("登录超时，请重新登录！",{
                            skin: 'layui-layer-lan'
                            ,closeBtn: 0
                            ,shift: 2
                        },function () {
                            top.location.href = serverPath.systemPath + "/login";
                        });
                        break;
                    case 500:
                        that.render(serverPath.systemPath+"/error/500");
                        break;
                    case 404:
                        that.render(serverPath.systemPath+"/error/404");
                        break;
                    case 403:
                        that.render(serverPath.systemPath+"/error/403");
                        break;
                    default:
                        that.render(serverPath.systemPath+"/error");
                }
                that.render.isError = true;
            }
        });
        return that;
    };

    //解析模板
    Class.prototype.parse = function(html, refresh, callback){
        var that = this
            ,isScriptTpl = typeof html === 'object' //是否模板元素
            ,elem = isScriptTpl ? html : $(html)
            ,elemTemp = isScriptTpl ? html : elem.find('*[template]')
            ,fn = function(options){
            var tpl = laytpl(options.dataElem.html())
                ,res = $.extend({
                params: router.params
            }, options.res);

            options.dataElem.after(tpl.render(res));
            typeof callback === 'function' && callback();

            try {
                options.done && new Function('d', options.done)(res);
            } catch(e){
                console.error(options.dataElem[0], '\n存在错误回调脚本\n\n', e)
            }
        }
            ,router = layui.router();

        elem.find('title').remove();
        that.container[refresh ? 'after' : 'html'](elem.children());

        router.params = that.params || {};

        //遍历模板区块
        for(var i = elemTemp.length; i > 0; i--){
            (function(){
                var dataElem = elemTemp.eq(i - 1)
                    ,layDone = dataElem.attr('lay-done') || dataElem.attr('lay-then') //获取回调
                    ,url = laytpl(dataElem.attr('lay-url')|| '').render(router) //接口 url
                    ,data = laytpl(dataElem.attr('lay-data')|| '').render(router) //接口参数
                    ,headers = laytpl(dataElem.attr('lay-headers')|| '').render(router); //接口请求的头信息

                try {
                    data = new Function('return '+ data + ';')();
                } catch(e) {
                    hint.error('lay-data: ' + e.message);
                    data = {};
                };

                try {
                    headers = new Function('return '+ headers + ';')();
                } catch(e) {
                    hint.error('lay-headers: ' + e.message);
                    headers = headers || {}
                };

                if(url){
                    view.req({
                        type: dataElem.attr('lay-type') || 'get'
                        ,url: url
                        ,data: data
                        ,dataType: 'json'
                        ,headers: headers
                        ,success: function(res){
                            fn({
                                dataElem: dataElem
                                ,res: res
                                ,done: layDone
                            });
                        }
                    });
                } else {
                    fn({
                        dataElem: dataElem
                        ,done: layDone
                    });
                }
            }());
        }

        return that;
    };

    //自动渲染数据模板
    Class.prototype.autoRender = function(id, callback){
        var that = this;
        $(id || 'body').find('*[template]').each(function(index, item){
            var othis = $(this);
            that.container = othis;
            that.parse(othis, 'refresh');
        });
    };

    //直接渲染字符
    Class.prototype.send = function(views, data){
        var tpl = laytpl(views || this.container.html()).render(data || {});
        this.container.html(tpl);
        return this;
    };

    //局部刷新模板
    Class.prototype.refresh = function(callback){
        var that = this
            ,next = that.container.next()
            ,templateid = next.attr('lay-templateid');

        if(that.id != templateid) return that;

        that.parse(that.container, 'refresh', function(){
            that.container.siblings('[lay-templateid="'+ that.id +'"]:last').remove();
            typeof callback === 'function' && callback();
        });

        return that;
    };

    //视图请求成功后的回调
    Class.prototype.then = function(callback){
        this.then = callback;
        return this;
    };

    //视图渲染完毕后的回调
    Class.prototype.done = function(callback){
        this.done = callback;
        return this;
    };

    //对外接口
    exports('view', view);
});